using System;
using System.Data;
using System.Globalization;
using System.Reflection;
using System.Web.UI;
using Web.Ajax;
using System.ComponentModel;

namespace Web.Ajax.Controls
{
	[ToolboxData("<{0}:GridColumn runat=\"server\" Name=\"?\" Binding=\"?\" />")]
	[ParseChildren(false)]    
    [Json(IgnoreParent=true, IgnoreNullMembers=true)]
	public class GridColumn : System.Web.UI.WebControls.WebControl
	{
		private string name="Column Name";
		public string Name
		{
			get { return name; }
			set { name = value; }
		}

		private string binding = "";
		public string Binding
		{
			get { return binding; }
			set { binding = value; }
		}

		private string headingAlign = "left";
		public string HeadingAlign
		{
			get { return headingAlign; }
			set { headingAlign = value; }
		}

		private string align = "left";
		public string Align
		{
			get { return align; }
			set { align = value; }
		}

		private string sort;
		public string Sort
		{
			get { return sort; }
			set { sort = value; }
		}

		private bool javascript = false;
		public bool Javascript
		{
			get { return javascript; }
			set { javascript = value; }
		}

		public string Function;

		private string verticalAlign = "top";
		public string VerticalAlign
		{
			get { return verticalAlign; }
			set { verticalAlign = value; }
		}

		private string padding;
		public string Padding
		{
			get { return padding; }
			set { padding = value; }
		}

		private string format;
		public string Format
		{
			get { return format; }
			set { format = value; }
		}

		private string template;
		public string Template
		{
			get { return template; }
			set { template = value; }
		}

		private string order = "Asc";
		public string Order
		{
			get { return order; }
			set { order = value; }
		}

		private string css;
		public string Css
		{
			get { return css; }
			set { css = value; }
		}

        private string onClick;
        public string OnClick
        {
            get { return onClick; }
            set { onClick = value; }
        }

        private bool editable = false;
        public bool Editable
        {
            get { return editable; }
            set { editable = value; }
        }

        private bool required;
        public bool Required
        {
            get { return required; }
            set { required = value; }
        }

        private string regEx;
        public string RegEx
        {
            get { return regEx; }
            set { regEx = value; }
        }


        private string defaultValue;
        public string DefaultValue
        {
            get { return defaultValue; }
            set { defaultValue = value; }
        }

        private string type;
        public string Type
        {
            get { return type; }
            set { type = value; }
        }

        private Options.Item[] options;
        public Options.Item[] Options
        {
            get { return options; }
            set { options = value; }
        }

        private int maxLength;
        public int MaxLength
        {
            get { return maxLength; }
            set { maxLength = value; }
        }

		public string OnChange{get;set;}

        public override System.Web.UI.WebControls.Unit Width
        {
            get
            {
                return base.Width;
            }
            set
            {
                base.Width = value;
            }
        }
        
        public override bool Visible
        {
            get
            {
                return base.Visible;
            }
            set
            {
                base.Visible = value;
            }
        }


		#region BindItemMethod
		public string BindMethodName;
		public string BindMethodType;

		public delegate string GetDataMethod(GridColumn column, DataRow row, Object Value);

		/// <summary>
		/// Sets the Method to use when binding a row item to this column. The Method must have the following signature:
		/// public static string GetCellData(GridColumn column, DataRow row);
		/// </summary>
		/// <param name="t">The type where the method can be located.</param>
		/// <param name="MethodName">The name of the method to use.</param>
		public void SetDataMethod(GetDataMethod BindMethod)
        {
            MethodInfo method = BindMethod.Method;
			string err = "Failed to Set BindMethod in GridColumn: " + Name + ". ";
			string sig = "\ne.g. public static string BindColumn(GridColumn column, DataRow row);";
			if (method == null)
				throw new Exception(err + "The Method cannot be null.");
            string MethodName = method.Name;
            BindMethodType = method.DeclaringType.AssemblyQualifiedName;
            BindMethodName = MethodName;
            if ((method.Attributes & MethodAttributes.Static) != MethodAttributes.Static)
				throw new Exception(err + "The Method: " + MethodName + " is not static. "+sig);
		}
		#endregion
       

		public virtual string GetItemJson(DataRow row)
		{
			
			string ErrMsg = "While Processing GridColumn \"" + Name + "\", ";
			object o = null;
			string html = null;
            bool RowEditable=Editable;
            if (row.Table.Columns.Contains("Editable"))
            {
                string s = row["Editable"].ToString();
                if (s == "False")
                    RowEditable = false;
            }
			if(!string.IsNullOrEmpty(BindMethodName)&&!string.IsNullOrEmpty(BindMethodType))
			{
				Type t = System.Type.GetType(BindMethodType);
				if (t == null)
					throw new Exception(ErrMsg+"Failed to get Bind Method Type: " + BindMethodType);
				MethodInfo method = t.GetMethod(BindMethodName);
				if(method==null)
					throw new Exception(ErrMsg+"Failed to get Bind Method: " + BindMethodName);
				try
				{
                    object val = null;
                    if (row.Table.Columns.Contains(Binding))
                        val = row[Binding];
                    if (val is DBNull)
                        val = null;
					o=method.Invoke(null, new object[] { this, row, val });
				}
				catch(Exception e)
				{
					string err = e.Message;
					if(e.InnerException!=null)
						err = e.InnerException.Message;
					throw new Exception(ErrMsg+"Failed to call BindMethod " + BindMethodName + "(). "+err);
				}
			}
			if (o != null && o is string)
				html = (string)o;
			else
			{
				if (string.IsNullOrEmpty(Binding))
					html = "";
				else
				{
                    object dbVal = DBNull.Value;
                    if(row.Table.Columns.Contains(Binding))
                        dbVal=row[Binding];
                    if (!(dbVal is DBNull))
                    {
                        if (dbVal is Web.Ajax.Controls.Options)
                        {
                            
                            html = Json.ConvertToJson(dbVal);
                            //Web.Ajax.Controls.OptionColumn oc=(Web.Ajax.Controls.OptionColumn)dbVal;
                            //html = "<img onclick=\""+oc.OnClick+"\" src=\""+Resources.ImageUrl(Resources.Images.DropDown)+"\" style=\"padding: 0 22px;\"></img>";
                        }
                        else if (dbVal is DateTime? && Editable && RowEditable)
                        {
                            html = Json.ConvertToJson(dbVal);
                        }
                        else
                        {
                            if (!string.IsNullOrEmpty(Format))
                            {
								var f = Format;
								if (f == "date")
									f = Web.Ajax.Data.Format.DateFormat;
								if(f=="datetime")
									f = Web.Ajax.Data.Format.DateTimeFormat;
                                if (dbVal is DateTime)
                                    html = ((DateTime)dbVal).ToString(f);
                                else if (dbVal is DateTime?)
                                {
                                    DateTime? date = (DateTime?)dbVal;
                                    if (date.HasValue)
                                        html = date.Value.ToString(f);
                                }
                                else
                                    html = string.Format(Format, dbVal);
                            }
                            else
                            {
                                if (dbVal is bool)
                                    html = dbVal.ToString().ToLower();
                                else
                                {
                                    html = dbVal.ToString();
                                }
                            }
                        }
                    }
 				}
			}
			return "\""+Binding+"\":" + Json.ConvertToJson(html);
		}

		protected override void AddParsedSubObject(object obj)
		{
			if (obj is LiteralControl)
				Template += ((obj as LiteralControl).Text.Replace("\r\n","").Replace("\t","").Trim());
		}
	}

    public class Options
    {
        public string OnClick;
        public Item[] Items;

		public Options()
		{
		}

        public Options(string OnClick)
        {
            this.OnClick = OnClick;
        }

        public Options(Item[] Items)
        {
            this.Items = Items;
        }

        public class Item
        {
			public string Value;
            public string Text;
            public string OnClick;
            public string Css;
			public string Resource;
        }
    }
}


